package math;

import java.awt.Graphics;

public class Vector2 
{
    public double x, y;
    
    public Vector2()
    {
	this.x = 0;
	this.y = 0;
    }
    public Vector2(Vector2 v)
    {
	this(v.x, v.y);
    }
    public Vector2(double x, double y)
    {
	this.x = x;
	this.y = y;
    }
    public Vector2 clone()
    {
	return new Vector2(this);
    }
    public void copy(Vector2 v)
    {
	this.x = v.y;
	this.y = v.y;
    }
    public void invert()
    {
	this.x = -this.x;
	this.y = -this.y;
    }
    public void scale(double scalar)
    {
	this.x*=scalar;
	this.y*=scalar;
    }
    public void normalize()
    {
	double len = Math.sqrt((this.x*this.x)+(this.y*this.y));
	if(len!=0 && len!=1)
	{
	    this.x/=len;
	    this.y/=len;
	}
	else if(len == 0)
	{
	    System.err.println("Zero length Vector2 was to be normalized\n");
	}
    }
    public void setLength(double length)
    {
	double len = Math.sqrt((this.x*this.x)+(this.y*this.y));
	if(len!=0)
	{
	    this.x/=len;
	    this.y/=len;
	    this.x*=length;
	    this.x*=length;
	}
	else
	{
	    System.err.println("Zero length Vector2 was to be normalized\n");
	}
    }
    public boolean isZeroLength()
    {
	return x!=0&&y!=0;
    }
    public boolean isNormal()
    {
	return Math.sqrt((this.x*this.x)+(this.y*this.y))==1.0;
    }
    public double getLength()
    {
	return Math.sqrt((this.x*this.x)+(this.y*this.y));
    }
    public double getTheta()
    {
	return (Math.atan(y/x))+(x<0?3.141592653589793d:6.283185307179586d)%(6.283185307179586d);
    }
    public Vector2 getDirection()
    {
	Vector2 r = new Vector2(this);
	double len = Math.sqrt((r.x*r.x)+(r.y*r.y));
	if(len!=0 && len!=1)
	{
	    r.x/=len;
	    r.y/=len;
	}
	else if(len == 0)
	{
	    System.err.println("Zero length Vector2 was to be normalized\n");
	}
	return r;
    }
    public Vector2 getInverse()
    {
	return new Vector2(-this.x, -this.y);
    }
    public Vector2 getNormR()
    {
	return new Vector2(-this.y, this.x);
    }
    public Vector2 getNormL()
    {
	return new Vector2(this.y, -this.x);
    }
    
    public double dot(Vector2 arg)
    {
	return ((this.x * arg.x) + (this.y * arg.y));
    }
    public double cross(Vector2 arg)
    {
	return ((this.x * arg.y) - (this.y * arg.x));
    }
    public void render(Graphics g)
    {
	this.render(Vector2.ORIGIN, g);
    }
    public void render(Vector2 base, Graphics g)
    {
	this.render(base, 10, g);
    }
    public void render(Vector2 base, double armLength, Graphics g)
    {
	g.drawLine((int)base.x, (int)base.y, (int)(base.x+this.x), (int)(base.y+this.y));
	double theta = (Math.atan(y/x))+(x<0?3.141592653589793d:6.283185307179586d)%(6.283185307179586d);
	if(Math.sqrt((this.x*this.x)+(this.y*this.y))!=0)
	{
	    g.drawLine((int)(base.x+this.x), (int)(base.y+this.y), (int)(base.x+this.x+armLength*Math.sin((-3.141592653589793d/4)+theta)), (int)(base.y+this.y-armLength*Math.cos((-3.141592653589793d/4)+theta)));
	    g.drawLine((int)(base.x+this.x), (int)(base.y+this.y), (int)(base.x+this.x-armLength*Math.cos((3.141592653589793d/4)-theta)), (int)(base.y+this.y+armLength*Math.sin((3.141592653589793d/4)-theta)));
	}
    }
    @Override
    public String toString()
    {
	return "("+this.x+", "+this.y+")";
    }
    
    public static final Vector2 ORIGIN = new Vector2(0,0);
    public static final Vector2 X_AXIS = new Vector2(1,0);
    public static final Vector2 Y_AXIS = new Vector2(0,1);
    public static final Vector2 i = new Vector2(1,0);
    public static final Vector2 j = new Vector2(0,1);
    
    public static Vector2 op_Add(Vector2 a, Vector2 b)
    {
	return new Vector2(a.x+b.x, a.y+b.y);
    }
    public static Vector2 op_Subtract(Vector2 a, Vector2 b)
    {
	return new Vector2(a.x-b.x, a.y-b.y);
    }
    public static Vector2 op_Multiply(Vector2 a, Vector2 b)
    {
	return new Vector2(a.x*b.x, a.y*b.y);
    }
    public static Vector2 op_Divide(Vector2 a, Vector2 b)
    {
	if(b.x!=0&&b.y!=0)
	{
	    return new Vector2(a.x/b.x, a.y/b.y);
	}
	else
	{
	    System.err.println("Zero length Vector2 was to be normalized\n");
	    return a;
	}
    }
    public static Vector2 op_Modulus(Vector2 a, Vector2 b)
    {
	if(b.x!=0&&b.y!=0)
	{
	    return new Vector2(a.x%b.x, a.y%b.y);
	}
	else
	{
	    System.err.println("Zero length Vector2 was to be normalized\n");
	    return a;
	}
    }
    
    public static Vector2 op_Add(Vector2 a, double scalar)
    {
	return new Vector2(a.x+scalar, a.y+scalar);
    }
    public static Vector2 op_Subtract(Vector2 a, double scalar)
    {
	return new Vector2(a.x-scalar, a.y-scalar);
    }
    public static Vector2 op_Multiply(Vector2 a, double scalar)
    {
	return new Vector2(a.x*scalar, a.y*scalar);
    }
    public static Vector2 op_Divide(Vector2 a, double scalar)
    {
	if(scalar != 0)
	{
	    return new Vector2(a.x/scalar, a.y/scalar);
	}
	else
	{
	    System.err.println("Attempted to divide by zero\n");
	    return a;
	}
    }
    public static Vector2 op_Modulus(Vector2 a, double scalar)
    {
	if(scalar != 0)
	{
	    return new Vector2(a.x%scalar, a.y%scalar);
	}
	else
	{
	    System.err.println("Attempted to divide by zero\n");
	    return a;
	}
    }
    
    public static double dot(Vector2 a, Vector2 b)
    {
	return ((a.x * b.x) + (a.y * b.y));
    }
    public static double cross(Vector2 a, Vector2 b)
    {
	return ((a.x * b.y) - (a.y * b.x));
    }
    public static double distBetween(Vector2 a, Vector2 b)
    {
	double dX = a.x-b.x;
	double dY = a.y-b.y;	
	return Math.sqrt((dX*dX)+(dY*dY));
    }
}
